package org.raymond.iworks.study.basic.structure.queue;

import java.util.Scanner;

public class QueueTest {

    public static void main(String[] args) {
        circleQueueTest();
    }

    // 队列是一个有序列表,可以用数组或链表来实现
    // 遵循先入先出(FIFO)原则,即先存入队列的数据,要先取出,后存入的数据要后取出
    private static void arrayQueueTest(){
        System.out.println("s(show): 显示队列");
        System.out.println("e(exit): 退出程序");
        System.out.println("a(add): 添加数据到队列");
        System.out.println("p(pop): 弹出数据");
        System.out.println("h(head): 查看队列头");

        ArrayQueue<Integer> arrayQueue = new ArrayQueue(3);
        char input = ' ';
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        while (loop) {
            input = scanner.next().charAt(0);
            switch (input) {
                case 's':
                    arrayQueue.showAll();
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                case 'a':
                    System.out.println("请输入一个数据");
                    int i = scanner.nextInt();
                    arrayQueue.add(i);
                    break;
                case 'p':
                    System.out.println("pop: " + arrayQueue.pop());
                    break;
                case 'h':
                    System.out.println("head: " + arrayQueue.peekHead());
                    break;
                default:
                    System.out.println("用法不对");
            }
        }
    }

    /**
     * 用数组模拟循环队列思路分析:
     * 1, max含义调整,增加一个用于约定的空位,即实际的有效数为max-1.
     * 2, front含义调整:原来是指向队列第一个元素的前一个位置,现在改为指向队列的第一个元素.
     * 即array[front]就是队列的第一个元素,初始值为0.
     * 3, tail含义调整:原来是指向队列最后一个元素,现在改为指向队列最后一个元素的后一个位置.
     * 因为希望空出一个空间作为约定,初始值为0,
     * 综合1,2,即第一个元素位置为0,最后一个元素的位置为-1.
     * 4, 当队列满时的判断条件:
     * 原来:tail==max-1,最大元素数的下标即为max-1
     * 现在:(tail+1)%max==front
     * 例:max=5的队列,添加5个元素,front=0,tail=5,(5+1)%5=1
     * 注:对一个数N取模,得到0～(N-1),此处即表示在判断第一个元素与最后一个元素是否为同一个元素,即是否满
     * 5, 当队列空的条件:
     * 原来:tail==front
     * 现在:tail==front
     * 6, 队列中有效数据的个数
     * size=(tail+max-front)%max
     */
    private static void circleQueueTest(){
        System.out.println("s(show): 显示队列");
        System.out.println("e(exit): 退出程序");
        System.out.println("a(add): 添加数据到队列");
        System.out.println("p(pop): 弹出数据");
        System.out.println("h(head): 查看队列头");

        // max中包含一个用于约定的空位,因此实际的最大有效数为max-1
        CircleQueue<Integer> arrayQueue = new CircleQueue<>(5+1);
        char input = ' ';
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        while (loop) {
            input = scanner.next().charAt(0);
            switch (input) {
                case 's':
                    arrayQueue.showAll();
                    break;
                case 'e':
                    scanner.close();
                    loop = false;
                    break;
                case 'a':
                    System.out.println("请输入一个数据");
                    int i = scanner.nextInt();
                    arrayQueue.add(i);
                    break;
                case 'p':
                    System.out.println("pop: " + arrayQueue.pop());
                    break;
                case 'h':
                    System.out.println("head: " + arrayQueue.peekHead());
                    break;
                case 't':
                    System.out.println("tail: " + arrayQueue.peekTail());
                    break;
                default:
                    System.out.println("用法不对");
            }
        }
    }
}
